package com.landmark;

import java.awt.EventQueue;
import java.io.FileWriter;
import java.net.SocketTimeoutException;
import java.util.Enumeration;
import java.util.Hashtable;
import javax.swing.JOptionPane;
import javax.swing.JTextArea;
import javax.swing.SwingWorker;
import org.htmlparser.Node;
import org.htmlparser.Parser;
import org.htmlparser.filters.TagNameFilter;
import org.htmlparser.nodes.TagNode;
import org.htmlparser.nodes.TextNode;
import org.htmlparser.util.NodeIterator;
import org.htmlparser.util.NodeList;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

public class HolstersBianchi extends SwingWorker<Boolean, Boolean> {

    FileWriter fw = null;
    FileWriter fwErrorFile = null;
    StringBuffer sb = new StringBuffer();
    int colPosCount = 0;
    Hashtable<String, String> htCatMainLinks = new Hashtable<String, String>();
    Hashtable<String, String> htCatSubLinks = new Hashtable<String, String>();
    Hashtable<String, String> htModelLinks = new Hashtable<String, String>();
    boolean appendLineFeed = false;
    boolean rowStart = false;
    Hashtable<String, Integer> htPosition = new Hashtable<String, Integer>();
    JTextArea txtArea = null;
    String status = null;
    UMProgressBar pBar = null;
    int lineCount = 0;

    /**
     * @param args
     */
    public void start() {
        try {

            String dirName = "./outputs/HolstersBianchiImages";

            Util.createDirectory(dirName);

            txtArea = Util.createOutputFile("HolsterBianchi");
            fw = new FileWriter(Util.getHelperBean().getOutputFile());
            fwErrorFile = new FileWriter(Util.getHelperBean().getErrorFile());
            HelperBean helperBean = Util.getHelperBean();

            // Process the main page to get the main category links which are on the left side menu of the page            
            processHomePageLinks();

            Enumeration mainCatEnum = htCatMainLinks.keys();
            while (mainCatEnum.hasMoreElements()) {
                processMainCategoryLinks(htCatMainLinks.get(mainCatEnum.nextElement()));
            }
            System.out.println(htCatSubLinks.size());
            Enumeration subCatKeys = htCatSubLinks.keys();
            while (subCatKeys.hasMoreElements()) {
                String link = subCatKeys.nextElement().toString();
                if (Util.getHelperBean().isTerminateCurrentProcess()) {
                    break;
                }
                txtArea.setText("Processing page: " + link + "\n");
                txtArea.paintImmediately(txtArea.getVisibleRect());

                //System.out.println(link);
                processSubCategoryLinks(htCatSubLinks.get(link));
            }

            System.out.println(htModelLinks.size());
            Enumeration modelKeys = htModelLinks.keys();

            txtArea.append("\nFiles are located at : " + helperBean.getOutputFile().getAbsolutePath() + "\n" + helperBean.getErrorFile().getAbsolutePath() + "\n");
            txtArea.append("Total products : " + htModelLinks.size() + "\n");
            txtArea.paintImmediately(txtArea.getVisibleRect());
            Util.getHelperBean().setLineCount(htModelLinks.size());
            lineCount = 0;
                pBar = new UMProgressBar();
            while (modelKeys.hasMoreElements()) {
                Util.getHelperBean().setCurrentCount(lineCount++);
                if (Util.getHelperBean().isTerminateCurrentProcess()) {
                    break;
                }
                String url = htModelLinks.get(modelKeys.nextElement());
                sb = new StringBuffer();
                //if (url.contains("model6365")) {
                htPosition = new Hashtable<String, Integer>();
                
                processHtml(url);
                

//                String str = sb.toString().replaceAll("\n", "").replaceAll("   ", "")// replce 3 spaces with empty space 
//                        .replaceAll("<tr>", "\n") // all <tr> with "new line"
//                        .replaceAll("<li>", "</li><li>").replaceAll("<h3>", "\n\n").replaceAll("<h2>", "\n").replaceAll("</h2>", "\n").replaceAll("<LMITNEWLINE>", "\n") // we are appending a new line depending on our requirement 
//                        .replaceAll("<tr valign=\"top\">", "\n") // replace with new line
//                        .replaceAll("<tr class=\"style1\">", "\n") // replace with new line
//                        .replaceAll("<tr bgcolor=\"#666666\">", "\n") // replace with new line
//                        .replaceAll("<tr bgcolor=\"#FFFFFF\">", "\n") // replace with new line
//                        .replaceAll("<tr bgcolor=\"#000000\">", "\n") // replace with new line
//                        .replaceAll("<tr bgcolor=\"#999999\">", "\n") // replace with new line
//                        .replaceAll("<tr class=\"prodgrid\">", "\n") // replace with new line
//                        .replaceAll("<tr class=\"finish\">", "\n") // replace with new line
//                        .replaceAll("<tr align=\"left\">", "\n") // replace with new line
//                        .replaceAll("<tr valign=\"top\" bgcolor=\"#999999\">", "\n") // replace with new line                        
//                        .replaceAll("<tr align=\"center\">", "\n") // replace with new line                        
//                        .replaceAll("</small>", "\n");
String str = sb.toString().replaceAll("\n", "").replaceAll("   ", "")// replce 3 spaces with empty space 
                        .replaceAll("<tr>", "\n") // all <tr> with "new line"
                        .replaceAll("<li>", "</li><li>").replaceAll("<h3>", "\n\n").replaceAll("<h2>", "\n").replaceAll("</h2>", "\n").replaceAll("<LMITNEWLINE>", "\n") // we are appending a new line depending on our requirement 
                        .replaceAll("<tr valign=\"top\">", "\n") // replace with new line
                        .replaceAll("<tr class=\"style1\">", "") // replace with new line
                        .replaceAll("<tr bgcolor=\"#666666\">", "") // replace with new line
                        .replaceAll("<tr bgcolor=\"#FFFFFF\">", "") // replace with new line
                        .replaceAll("<tr bgcolor=\"#000000\">", "") // replace with new line
                        .replaceAll("<tr bgcolor=\"#999999\">", "") // replace with new line
                        .replaceAll("<tr class=\"prodgrid\">", "") // replace with new line
                        .replaceAll("<tr class=\"finish\">", "") // replace with new line
                        .replaceAll("<tr align=\"left\">", "") // replace with new line
                        .replaceAll("<tr valign=\"top\" bgcolor=\"#999999\">", "") // replace with new line                        
                        .replaceAll("<tr align=\"center\">", "") // replace with new line                        
                        .replaceAll("</small>", "");

                String[] strArr = str.split("\n");
                StringBuffer sb1 = new StringBuffer();
                for (String str1 : strArr) {
                    sb1.append(str1.replaceFirst(",", "") + "\n");
                }
                fw.write(sb1.toString());
//                    String[] splittedString = str.split("\n");                    
//                    
//                    for( int i = 0; i< splittedString.length; i++ ) {
//                        if( i == 1 ) {
//                            fw.write("\nDescription :\n"+splittedString[i]); 
//                        }else {
//                            fw.write(splittedString[i]); 
//                        }
//                    }
                fw.write("\n");
                fw.flush();
                if( Util.getHelperBean().getLineCount() == lineCount ) {
                    Util.getHelperBean().setProcessingDone(true);
                    pBar.close();
                }
                EventQueue.invokeLater(pBar);

            }
            fw.close();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                fw.close();
            } catch (Exception e1) {
                // TODO: handle exception
            }
        }

        status = "Done processing.";
        if (Util.getHelperBean().isTerminateCurrentProcess()) {
            status = "Process Terminated";
        }
        txtArea.append("\n" + status);
        txtArea.paintImmediately(txtArea.getVisibleRect());
    }

    @Override
    protected Boolean doInBackground() throws Exception {
        start();
        return true;
    }

    @Override
    protected void done() {
        JOptionPane.showMessageDialog(Util.getHelperBean().getDataPanel(), status);
        Util.getHelperBean().setTerminateCurrentProcess(false);
        Util.getHelperBean().getToggleButton().setEnabled(false);
    }

    private void processHtml(String aUrl) {
        try {
            Parser parser = Util.getParserFromUrl(aUrl, null);

            NodeList nl = parser.parse(null);
            NodeList tableNodes = nl.extractAllNodesThatMatch(new TagNameFilter("td"), true);
            Node targetTableNode = tableNodes.elementAt(2);// retrives the table content where the description starts which we are intersetd in.			

            iterateTag(targetTableNode);
            Elements imageUrl = Util.getHelperBean().getInputHTML().getElementsByTag("blockquote").select("img[src$=.jpg]");
            if( imageUrl.size() == 0 ) {
                imageUrl = Util.getHelperBean().getInputHTML().getElementsByTag(".products").select("img[src$=.jpg]");
            }
            for (Element ele : imageUrl) {
                //sb.append(ele.absUrl("src"));
                //sb.append("<#NEWLINE#>");
                System.out.println(ele.absUrl("src"));
                Util.saveImage(ele.absUrl("src"), "./outputs/HolstersBianchiImages", null);
            }
        }catch (SocketTimeoutException e) {
            processHtml(aUrl);                            
        } catch (Exception e) {
            try {                
                fwErrorFile.write(aUrl + " \n" + e.getMessage() + " \n");
                fwErrorFile.flush();                
            } catch (Exception e1) {                
            }
        } 
    }

    private void iterateTag(Node aNodeList) throws Exception {
        //try{
        //sb = new StringBuffer();
        if (aNodeList instanceof TextNode) {
            // downcast to TextNode
            TextNode text = (TextNode) aNodeList;
            // do whatever processing you want with the text
            //System.out.println (text.getText ());
            //if( !text.getText().contains("HOME &gt;") ) {
            sb.append(text.getText().replaceAll(",", "&#44;"));// manipulating for table data which contains commas in one column
            if (appendLineFeed) {
                sb.append("<LMITNEWLINE>");
                appendLineFeed = false;
            }
            //}
        } /*
         * if (aNodeList instanceof RemarkNode) { // downcast to RemarkNode
         * RemarkNode remark = (RemarkNode)aNodeList; // do whatever processing
         * you want with the comment }
         */ else if (aNodeList instanceof TagNode) {
            // downcast to TagNode
            TagNode tag = (TagNode) aNodeList;
            // append a TR in the final string, so that we can process the final out as we need by replacing the TR with watever character we want
            if (tag.getRawTagName().equalsIgnoreCase("tr")) {
                rowStart = true;
                colPosCount = 0;
                if (tag.toHtml().equalsIgnoreCase("<tr valign=\"top\">")) {
                    //System.out.println("An end tag : " + tag.getTagName());
                    //colPosCount = 0;
                    processHtPosition();
                } else if (tag.toHtml().equalsIgnoreCase("<tr class=\"style1\">")) {
                    processHtPosition();
                }
                sb.append(tag.toHtml());
            }
            if (tag.getRawTagName().equalsIgnoreCase("th")) {
                sb.append(",");
            }
            // Some headings contain small tag before them, we have to filter them to format the output
            if (tag.getRawTagName().equalsIgnoreCase("/small")) {
                sb.append("</small>");
            }
            if (tag.getRawTagName().equalsIgnoreCase("li")) {
                sb.append("<li>");
            }
            if (tag.getRawTagName().equalsIgnoreCase("h3")) {
                sb.append("<h3>");
                appendLineFeed = true;
            }
            if (tag.getRawTagName().equalsIgnoreCase("img")) {
                String imageSrc = tag.getAttribute("src");
                if (imageSrc != null && imageSrc.contains("_s")) {
                    String altText = tag.getAttribute("alt");
                    sb.append(imageSrc);
                }
            }
            if (tag.getRawTagName().equalsIgnoreCase("h2")) {
                sb.append("<h2>");
                appendLineFeed = true;
            }
            // replace all the occurances of TD's with a comma for readability in the output file
            if (tag.getRawTagName().equalsIgnoreCase("td")) {
                String rowSpanValue = tag.getAttribute("rowspan");
                String strPos = "" + colPosCount;
                if (htPosition.containsKey(strPos)) {
                    System.out.println("contain the key : " + colPosCount);
                    sb.append(",");
                }
                // if we have rowspan, we have to add a comma in each line to get comma seperated values for the data 
                // so getting how many rows has to have commas and at which position of td is comma is to be placed
                if (rowSpanValue != null) {
                    int colPosition = colPosCount;
                    String strCount = "" + colPosition;
                    System.out.println("RowSPanValue : " + rowSpanValue + "\t\t###Column pos  : " + colPosCount);
                    htPosition.put(strCount, Integer.parseInt(rowSpanValue));

                }
                //to do 
                sb.append(",");

                colPosCount++;
                //sb.append(",");
            }
            // process recursively (nodes within nodes) via getChildren()				
            NodeList nl = tag.getChildren();
            if (null != nl) {
                try {
                    for (NodeIterator i = nl.elements(); i.hasMoreNodes();) {
                        iterateTag(i.nextNode());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void processHomePageLinks() {
        try {
            Document doc = Jsoup.connect("http://holsters.com").get();
            Elements catElements = doc.getElementsByClass("category_menu").select("a[href]");
            for (Element element : catElements) {
                //System.out.println(element.attr("abs:href"));
                htCatMainLinks.put(element.attr("abs:href"), element.attr("abs:href"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void processMainCategoryLinks(String aUrl) {
        try {
            Document doc = Jsoup.connect(aUrl).get();
            Elements catSubElements = doc.select("a[href]");
            for (Element element : catSubElements) {
                String link = element.attr("abs:href");
                if (link.toLowerCase().contains(aUrl.toLowerCase()) && link.length() > aUrl.length()) {
                    int lastDotIndex = link.lastIndexOf(".");
                    String linkExtension = null;
                    if (lastDotIndex != 15) {
                        linkExtension = link.substring(lastDotIndex + 1, link.length());
                    }
                    if (link.toLowerCase().contains("index.asp") || linkExtension == null) {
                        htCatSubLinks.put(link.toLowerCase(), link);
                    } else {
                        htModelLinks.put(link.toLowerCase(), link);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void processSubCategoryLinks(String aUrl) {
        try {
            //System.out.println(aUrl);
            Document doc = Jsoup.connect(aUrl).get();
            Elements modelElements = doc.select("a[href]");
            int count = 0;
            for (Element element : modelElements) {
                String link = element.attr("abs:href");

                String aUrlSubString = aUrl.substring(0, aUrl.lastIndexOf("/"));
                //System.out.println(link);
                String linkSubString = null;
                if (link.lastIndexOf("/") != -1) {
                    linkSubString = link.substring(0, link.lastIndexOf("/"));
                }
                if (aUrlSubString.equalsIgnoreCase(linkSubString)) {
                    if (!link.toLowerCase().contains("index.asp")) {
                        htModelLinks.put(link.toLowerCase(), link);
                        count++;
                        //System.out.println(link);
                    }
                }
            }
            //System.out.println(count);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void processHtPosition() {
        Enumeration keys = htPosition.keys();
        while (keys.hasMoreElements()) {
            String key = (String) keys.nextElement();
            Integer value = htPosition.get(key);

            System.out.println("Key : " + key + "###value: " + value);
            value--;
            if (value != 0) {
                htPosition.put(key, value);
            } else {
                htPosition.remove(key);
            }
        }
    }
}
